//


import UIKit
import CoreData


class WP_CoreDataModel: NSObject {
    
    var entityName:String! //表名
    
    
    static let coreDataManager :WP_CoreDataModel = WP_CoreDataModel()
    
    //MARK:设置表name
    func setEntityName(text:String) {
        entityName = text
//        print("--------\(String(describing: entityName))")
    }
    
    //MARK:沙盒路径(4)
    lazy var applicationDocumentsDirectory: URL = {
        // The directory the application uses to store the Core Data store file. This code uses a directory named "me.appkitchen.cd" in the application's documents Application Support directory.
        let urls = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
        return urls[urls.count-1]
    }()
    //MARK:模型对象(3)
    lazy var managedObjectModel: NSManagedObjectModel = {
        // The managed object model for the application. This property is not optional. It is a fatal error for the application not to be able to find and load its model.
        let modelURL = Bundle.main.url(forResource: "WorkPlanData", withExtension: "momd")!
        return NSManagedObjectModel(contentsOf: modelURL)!
    }()
    //MARK:持久化存储库(2)
    lazy var persistentStoreCoordinator: NSPersistentStoreCoordinator = {
        // The persistent store coordinator for the application. This implementation creates and returns a coordinator, having added the store for the application to it. This property is optional since there are legitimate error conditions that could cause the creation of the store to fail.
        // Create the coordinator and store
        let coordinator = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel)
        let path = self.applicationDocumentsDirectory.appendingPathComponent("Wp.sqlite")
        var failureReason = "There was an error creating or loading the application's saved data."
        var options = [NSMigratePersistentStoresAutomaticallyOption:true, NSInferMappingModelAutomaticallyOption:true]
        
        do {
            try coordinator.addPersistentStore(ofType: NSSQLiteStoreType, configurationName: nil, at: path, options: options)
        } catch {
            // Report any error we got
            var dict = [String: AnyObject]()
            dict[NSLocalizedDescriptionKey] = "Failed to initialize the application's saved data" as AnyObject?
            dict[NSLocalizedFailureReasonErrorKey] = failureReason as AnyObject?
            dict[NSUnderlyingErrorKey] = error as NSError
            
            let wrappedError = NSError(domain: "YOUR_ERROR_DOMAIN", code: 9999, userInfo: dict)
            // Replace this with code to handle the error appropriately.
            // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
            NSLog("Unresolved error \(wrappedError), \(wrappedError.userInfo)")
            abort()
        }
        
        return coordinator
    }()
    //MARK:上下文(1)
    lazy var managedObjectContext: NSManagedObjectContext = {
        // Returns the managed object context for the application (which is already bound to the persistent store coordinator for the application.) This property is optional since there are legitimate error conditions that could cause the creation of the context to fail.
        let coordinator = self.persistentStoreCoordinator
        var managedObjectContext = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)
        managedObjectContext.persistentStoreCoordinator = coordinator
        
        return managedObjectContext
    }()
    
    
    //增加数据
    func saveData(parameter:Dictionary<String, Any>,success:(()->()),fail:(()->())) {
        
        if parameter.keys.count <= 0 {
            return
        }
        let manageContext = managedObjectContext
        let entityOne = NSEntityDescription.entity(forEntityName: entityName, in: manageContext)
        let itemS = NSManagedObject.init(entity: entityOne!, insertInto: manageContext)
        for (key,value) in parameter {
            itemS.setValue(value, forKey: key)
        }
        
        do {
            try manageContext.save()
            success()
            //print("..........\(itemS)")
        } catch{
            print("存储错误...")
            fail()
        }
    }
    
    
    //删除
    func deleteData(key:Any,success:(()->()),fail:(()->())) {
        let manageContext = managedObjectContext
        //通过管理对象上下文，获得实体名称，获得实体对象
        let entity = NSEntityDescription.entity(forEntityName: entityName, in: managedObjectContext)
        let fetchRequest = NSFetchRequest<NSFetchRequestResult>.init(entityName: entityName)
        fetchRequest.predicate = NSPredicate(format: (key as AnyObject) as! String )
        //设置需要提取数据的实体对象
        fetchRequest.entity = entity
        
        do {
            
            // 执行管理对象上下文数据的提取操作，并存入一个数组
            let results:[AnyObject]? = try managedObjectContext.fetch(fetchRequest)
            
            for obj in results! {
                manageContext.delete(obj as! NSManagedObject)
            }
            
            try manageContext.save()
            success()
            
        } catch{
            print("存储错误...")
            fail()
        }
    }
    
    
    //修改
    func updateData(parameter:Dictionary<String, Any>,key:Any,success:(()->()),fail:(()->())) {
        let manageContext = managedObjectContext
        //通过管理对象上下文，获得实体名称，获得实体对象
        let entityOne = NSEntityDescription.entity(forEntityName: entityName, in: manageContext)
        //创建查询请求
        let fetchRequest = NSFetchRequest<NSFetchRequestResult>.init(entityName: entityName)
        //        fetchRequest.fetchOffset = 0
        //        设置提取数据的数量
        //        fetchRequest.fetchLimit = 10
        //        设置需要提取数据的实体对象
        fetchRequest.entity = entityOne
        fetchRequest.predicate = NSPredicate(format: (key as AnyObject) as! String)
        //获取数据
        do {
            let results = try manageContext.fetch(fetchRequest)
            //找到修改的数据
            // let oneObj:NSManagedObject = results[aIndxPath.row] as! NSManagedObject
            //oneObj.setValue(upStr, forKey: "textStr")
            for obj in results {
                for (key,value) in parameter {
                    if !((value as AnyObject).isEqual("")) {
                        (obj as! NSManagedObject).setValue(value, forKey: key)
                    }
                }
            }
            
            do {
                try manageContext.save()
                //                do {
                //                    let results1 = try manageContext.fetch(fetchRequest)
                success()
                
            } catch{
                print("存储错误...")
                fail()
            }
        } catch{
            print("修改错误...")
            fail()
        }
    }
    
    
    //查询
    func readData(sequenceKeys:Array<Any>,ascending:Bool,filterStr:String?,success:((_ result:Array<Any>)->()),fail:(()->())) {
        let manageContext = managedObjectContext
        //通过管理对象上下文，获得实体名称，获得实体对象
        let entity = NSEntityDescription.entity(forEntityName: entityName, in: managedObjectContext)
        //创建一个数据提取请求对象
        let fetchReq = NSFetchRequest<NSFetchRequestResult>(entityName: entityName)
        //        设置提取数据的页数
        //        fetchReq.fetchOffset = 0
        //        设置提取数据的数量
        //        fetchReq.fetchLimit = 10
        //        设置需要提取数据的实体对象
        fetchReq.entity = entity
        
        //排序
        if sequenceKeys.count > 0 {
            var array = Array<Any>()
            
            for key in sequenceKeys {
                
                let sort = NSSortDescriptor(key: key as? String, ascending: ascending, selector: nil)
                array.append(sort)
            }
            if array.count > 0 {
                fetchReq.sortDescriptors = array as? [NSSortDescriptor]
            }
        }
        
        //条件
        if filterStr != nil {
            //  创建一个谓词对象，设置提取数据的查询条件。谓词被用来指定数据被获取，或者过滤的方式
            let predicate = NSPredicate(format: filterStr!)//"finish= 'John' "
            //  设置数据提取请求的谓词属性
            fetchReq.predicate = predicate
        }
        
        do {
            let results = try manageContext.fetch(fetchReq)
            success(results)
            
        } catch{
            print("查询错误...")
            fail()
        }
    }
    
    
}
